import BaseScene, { SceneConfig } from '../../components/scenes/BaseScene';
import {
  BoxBufferGeometry,
  BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  MeshNormalMaterial,
  MeshPhongMaterial,
  PlaneGeometry,
  PointLight,
  SphereBufferGeometry,
} from 'three';
import * as THREE from 'three';

/**
 * 外线框的实现思路是：
 * 通过对mesh的外层包一个大一点的物体即可,在给定材质时，设置为side: THREE.BackSide
 * 这样由于裁剪会将其内部与原模型之间的距离渲染，
 * 看起来像是外边包围的线条
 */
class BasicScene extends BaseScene {
  constructor(config) {
    super(config);
    const { camera } = this;
    this.addPlane();
    this.addLight();
    this.addGeometry();
    camera.position.setY(300);
    camera.position.setX(300);
    camera.position.setZ(300);
    camera.lookAt(0, 0, 0);
  }

  private addPlane() {
    const { scene } = this;
    scene.background = new Color(0xaaaaaa);
    const planeGeometry = new PlaneGeometry(1000, 1000);
    const material = new MeshPhongMaterial();
    planeGeometry.rotateX(-Math.PI / 2);
    const boxMesh = new Mesh(planeGeometry, material);
    boxMesh.receiveShadow = true;
    boxMesh.position.setY(-70);
    scene.add(boxMesh);
  }
  private addGeometry() {
    const { scene } = this;
    const geometry = new SphereBufferGeometry(50, 32, 16);
    const mesh = new Mesh(geometry, new MeshNormalMaterial());
    mesh.castShadow = true;
    scene.add(mesh);
    const outlineMaterial1 = new THREE.MeshBasicMaterial({
      color: 0xff0000,
      side: THREE.BackSide,//注意，此处必须设置为backSide，否则会出现红色覆盖掉mesh
    });
    const outlineMesh1 = new THREE.Mesh(geometry, outlineMaterial1);
    outlineMesh1.position.set(
      mesh.position.x,
      mesh.position.y,
      mesh.position.z
    );
    outlineMesh1.scale.multiplyScalar(1.05);
    scene.add(outlineMesh1);
  }
  private addWireframeGeometry1() {}
  private addLight() {
    const { scene, renderer } = this;
    const light = new PointLight(0xffffff, 0.7);
    light.castShadow = true;
    light.position.setY(300);
    scene.add(light);
    scene.add(new THREE.PointLightHelper(light, 10));
    renderer['shadowMapEnabled'] = true;
  }
}

export const render = (config: SceneConfig): BasicScene => {
  const renderWater = new BasicScene(config);
  renderWater.run();
  return renderWater;
};
